package com.wuxi.common.utils;

import com.wuxi.common.config.ShardingProperties;
import jakarta.annotation.PostConstruct;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import java.sql.DatabaseMetaData;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;

/**
 * 分表自动创建服务
 */
@Slf4j
@Component
@RequiredArgsConstructor
public class TableAutoCreator {

    private final JdbcTemplate jdbcTemplate;
    private final ShardingProperties shardingProperties;

    /**
     * 应用启动时检查并创建当前月和下月的表
     */
    @PostConstruct
    public void init() {
        log.info("初始化分表...");
        for (String baseTable : shardingProperties.getTables()) {
            // 检查并创建当前月表
            createTableIfNotExists(baseTable, LocalDate.now());
            // 检查并创建下月表
            createTableIfNotExists(baseTable, LocalDate.now().plusMonths(1));
        }
    }

    /**
     * 定时任务，每月25日检查并创建下月分表
     * 防止初始化时未创建或有新表添加
     */
    @Scheduled(cron = "0 0 1 25 * ?") // 每月25日凌晨1点执行
    public void scheduledCreateNextMonthTable() {
        log.info("执行定时创建下月分表任务...");
        LocalDate nextMonth = LocalDate.now().plusMonths(1);
        for (String baseTable : shardingProperties.getTables()) {
            createTableIfNotExists(baseTable, nextMonth);
        }
    }

    /**
     * 检查表是否存在，不存在则创建
     */
    public void createTableIfNotExists(String baseTableName, LocalDate date) {
        String shardingTableName = ShardingUtil.getShardingTableName(baseTableName, date);

        // 检查表是否已存在
        if (tableExists(shardingTableName)) {
            log.debug("分表 {} 已存在，无需创建", shardingTableName);
            return;
        }

        // 创建分表，复制基础表结构
        try {
            String createSql = "CREATE TABLE " + shardingTableName + " LIKE " + baseTableName;
            jdbcTemplate.execute(createSql);

            // 为统计查询添加索引
            createStatisticIndexes(shardingTableName);

            log.info("成功创建分表: {}", shardingTableName);
        } catch (Exception e) {
            log.error("创建分表 {} 失败", shardingTableName, e);
        }
    }

    /**
     * 检查数据库表是否存在
     */
    private boolean tableExists(String tableName) {
        try {
            DatabaseMetaData metaData = jdbcTemplate.getDataSource().getConnection().getMetaData();
            ResultSet rs = metaData.getTables(null, null, tableName, new String[]{"TABLE"});
            return rs.next();
        } catch (SQLException e) {
            log.error("检查表格 {} 是否存在时出错", tableName, e);
            return false;
        }
    }

    /**
     * 为分表创建适合统计查询的索引
     */
    private void createStatisticIndexes(String tableName) {
        try {
            // 根据实际表结构创建索引
            if (tableName.startsWith("yarn_action_")) {
                jdbcTemplate.execute("CREATE INDEX idx_yarn_action_time ON " + tableName + "(create_time)");
                jdbcTemplate.execute("CREATE INDEX idx_yarn_action_type ON " + tableName + "(action_type)");
            } else if (tableName.startsWith("transport_action_")) {
                jdbcTemplate.execute("CREATE INDEX idx_transport_action_time ON " + tableName + "(create_time)");
                jdbcTemplate.execute("CREATE INDEX idx_transport_action_status ON " + tableName + "(status)");
            }
        } catch (Exception e) {
            log.warn("为表 {} 创建索引失败", tableName, e);
        }
    }
}
